//
//  QSRouter.swift
//  TestSwift
//
//  Created by Song on 2022/1/3.
//  Copyright © 2022 Song. All rights reserved.
//

import UIKit

class QSRouter {
    /// 跳转类型
    enum QSOpenType {
        case push
        case present
        case presentWithNav
    }
    
    /// 界面跳转
    /// - Parameters:
    ///   - tabVc: 要跳转哪个tabBar控制器
    ///   - vc: 要跳转到哪个控制器
    ///   - returnVc: 返回按钮和右滑手势返回哪个控制器
    ///   - openType: 跳转方式
    ///   - isAnimated: 跳转时是否需要动画，默认有动画
    ///   - isReuse: 是否复用已存在的控制器，默认不复用
    ///   - presentCompletion: present跳转完成后回调
    class func qs_open(tabVc: AnyClass? = nil, vc: AnyClass, returnVc: AnyClass? = nil, openType: QSOpenType = .push, isAnimated: Bool = true, isReuse: Bool = false, presentCompletion: (()->Void)? = nil) {
        // 跳转tabbar子控制器
        if let tabVc = tabVc {
            qs_openTabBarVc(tabVc)
        }
        
        // 获取当前控制器
        guard let currentVc = qs_getCurrentVc() else { return }
        // 可路由的控制器
        guard let routableVc = (vc as? QSRoutable.Type)?.qs_init() else {
            fatalError("没有遵守QSRoutable协议")
        }
        
        // push跳转
        if openType == .push {
            guard let nav = currentVc.navigationController else {
                fatalError("没有导航控制器，不能进行push跳转")
            }
            
            if isReuse {
                // 复用栈中存在的控制器
                let reuseVc = nav.children.first { child in
                    return child.isKind(of: vc)
                }
                
                if let reuseVc = reuseVc {
                    nav.popToViewController(reuseVc, animated: isAnimated)
                    return
                }
            }
            
            // push
            qs_pushVc(routableVc, returnVc: returnVc, animated: isAnimated)
            return
        }
        
        // present跳转
        if openType == .present {
            routableVc.hidesBottomBarWhenPushed = true
            currentVc.present(routableVc, animated: isAnimated, completion: presentCompletion)
            routableVc.hidesBottomBarWhenPushed = true
            return
        }
        
        // 带nav的present跳转
        if openType == .presentWithNav {
            let navVc = UINavigationController.init(rootViewController: routableVc)
            currentVc.present(navVc, animated: isAnimated, completion: presentCompletion)
            routableVc.hidesBottomBarWhenPushed = true
            return
        }
    }
    
    /// 获取当前控制器
    class func qs_getCurrentVc() -> UIViewController? {
        guard let rootVc = qs_keyWindow()?.rootViewController else { return nil }
        
        if let presentedVc = rootVc.presentedViewController {
            if let navVc = presentedVc as? UINavigationController {
                return navVc.visibleViewController
            } else {
                return presentedVc
            }
        }
        
        if let tabBarVc = qs_getTabBarVc() {
            if let navVc = tabBarVc.selectedViewController as? UINavigationController {
                return navVc.visibleViewController
            } else {
                return tabBarVc.selectedViewController
            }
        }
        
        if let rootNavVc = rootVc as? UINavigationController {
            return rootNavVc.visibleViewController
        }
        return rootVc
    }
    
    /// 获取keyWindow
    private class func qs_keyWindow() -> UIWindow? {
        if #available(iOS 13.0, *) {
            return UIApplication.shared.connectedScenes
                    .filter({$0.activationState == .foregroundActive})
                    .map({$0 as? UIWindowScene})
                    .compactMap({$0})
                    .first?.windows
                    .filter({$0.isKeyWindow}).first
        } else {
            return UIApplication.shared.keyWindow
        }
    }
    
    /// 获取TabBar控制器
    private class func qs_getTabBarVc() -> UITabBarController? {
        guard let rootVc = qs_keyWindow()?.rootViewController else { return nil }
        
        if let tabBarVc = rootVc as? UITabBarController {
            return tabBarVc
        }
        
        return nil
    }
    
    /// 跳转到TabBarController中的某个tab
    /// - Parameter subVc: tab子控制器
    private class func qs_openTabBarVc(_ subVc: AnyClass) {
        guard let tabBarVc = qs_getTabBarVc() else { return }
        guard let tabBarVcs = tabBarVc.viewControllers else { return }
        
        for (i, tabSubVc) in tabBarVcs.enumerated() {
            if let navVc = tabSubVc as? UINavigationController {
                if navVc.children.first?.classForCoder == subVc {
                    if let currentVC = qs_getCurrentVc() {
                        currentVC.navigationController?.popToRootViewController(animated: false)
                    }
                    tabBarVc.selectedIndex = i
                    break
                }
            } else {
                if tabSubVc.classForCoder == subVc {
                    tabBarVc.selectedIndex = i
                    break
                }
            }
        }
    }
    
    /// push控制器
    /// - Parameters:
    ///   - vc: 要push到哪个控制器
    ///   - returnVc: 返回按钮和右滑手势返回哪个控制器
    ///   - animated: 跳转时是否需要动画
    private class func qs_pushVc(_ vc: UIViewController, returnVc: AnyClass? = nil, animated: Bool) {
        guard let currentVc = qs_getCurrentVc() else { return }
        
        // push控制器
        vc.hidesBottomBarWhenPushed = true
        currentVc.navigationController?.pushViewController(vc, animated: animated)
        
        // 删除导航控制器中多余控制器
        guard let returnVc = returnVc else { return }
        guard var navChildVcs = vc.navigationController?.viewControllers else { return }
        
        // 获取要返回的目标控制器
        var targetVc: UIViewController? = nil
        for subVc in navChildVcs {
            if subVc.isKind(of: returnVc) {
                targetVc = subVc
                break
            }
        }
        
        // 目标控制器
        guard let targetVc = targetVc else { return }
        guard let targetVcIndex = navChildVcs.firstIndex(of: targetVc) else { return }
        
        // 移除目标控制器与当前控制器之间的所有控制器
        let range = NSRange.init(location: targetVcIndex + 1, length: navChildVcs.count - 1 - (targetVcIndex + 1))
        if let rng = Range.init(range) {
            navChildVcs.removeSubrange(rng)
            vc.navigationController?.viewControllers = navChildVcs
        }
    }
}
